package cn.com.bluemoon.daps.model.service.impl;

import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.enums.BmStatus;
import cn.com.bluemoon.daps.common.enums.DatabaseType;
import cn.com.bluemoon.daps.common.exception.DapException;
import cn.com.bluemoon.daps.common.toolkit.CheckUtils;
import cn.com.bluemoon.daps.model.dto.SubordinateKeyDto;
import cn.com.bluemoon.daps.model.entity.DapDataModel;
import cn.com.bluemoon.daps.model.entity.DapDataModelSubordinateKey;
import cn.com.bluemoon.daps.model.entity.DapDataModelTableField;
import cn.com.bluemoon.daps.model.mapper.DapDataModelSubordinateKeyMapper;
import cn.com.bluemoon.daps.model.mapper.DapDataModelTableFieldMapper;
import cn.com.bluemoon.daps.model.service.DapDataModelService;
import cn.com.bluemoon.daps.model.service.DapDataModelSubordinateKeyService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 模型下属表索引信息表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2020-08-07
 */
@Slf4j
@Service
public class DapDataModelSubordinateKeyServiceImpl extends ServiceImpl<DapDataModelSubordinateKeyMapper, DapDataModelSubordinateKey> implements DapDataModelSubordinateKeyService {


    @Autowired
    DapDataModelTableFieldMapper dapDataModelTableFieldMapper;

    @Autowired
    DapDataModelSubordinateKeyMapper dapDataModelSubordinateKeyMapper;

    @Resource
    DapDataModelService dapDataModelService;

    /**
     * 通过模型中的表id获得索引列表
     * @return
     */
    @Override
    public List<SubordinateKeyDto> getKeyList(String id) {

        // 根据表id查询索引列表
        List<DapDataModelSubordinateKey> keys = getBaseMapper()
                .selectList(new LambdaQueryWrapper<DapDataModelSubordinateKey>()
                .eq(DapDataModelSubordinateKey::getModelTableId, id)
                .eq(DapDataModelSubordinateKey::getBmStatus, BmStatus.ON.getCode()));
        // 通过索引中的字段id列表查询字段名
        List<SubordinateKeyDto> list = new ArrayList<>();
        if(!keys.isEmpty()){
            String collect = keys.stream().map(DapDataModelSubordinateKey::getFieldIds).collect(Collectors.joining(","));
            String[] split = collect.split(",");
            // 获得字段id集合
            List<String> ids = Arrays.asList(split);
            // 查询出所有的字段信息
            List<DapDataModelTableField> dapDataModelTableFields = dapDataModelTableFieldMapper.selectBatchIds(ids);
            keys.forEach(k ->{//
                List<String> strings = Arrays.asList(k.getFieldIds().split(","));
                List<DapDataModelTableField> fields = dapDataModelTableFields.stream()
                        .filter(d -> k.getFieldIds().contains(d.getId())).collect(Collectors.toList());
                List<DapDataModelTableField> fieldList = Lists.newArrayList();
                // 按照字段原本的顺序进行封装
                strings.forEach(s -> {
                    List<DapDataModelTableField> tableFields = fields.stream().filter(f -> f.getId().equals(s)).collect(Collectors.toList());
                    if(!tableFields.isEmpty()){
                        fieldList.addAll(tableFields);
                    }
                });
                SubordinateKeyDto subordinateKeyDto = new SubordinateKeyDto();
                BeanUtils.copyProperties(k, subordinateKeyDto);
                subordinateKeyDto.setFieldNames(fieldList);
                list.add(subordinateKeyDto);
            });
        }
        return list;
    }

   /* *//**
     * 删除字段前判断字段是否有索引
     * @param modelTableId
     * @return
     *//*
    @Override
    public String getList(String modelTableId, String fieldId) {

        List<DapDataModelSubordinateKey> dapDataModelSubordinateKeys = getBaseMapper()
                .selectList(new LambdaQueryWrapper<DapDataModelSubordinateKey>()
                .eq(DapDataModelSubordinateKey::getModelTableId, modelTableId)
                .eq(DapDataModelSubordinateKey::getBmStatus, BmStatus.ON.getCode()));
        // 索引列表不为空
        if(!dapDataModelSubordinateKeys.isEmpty()){
            String collect = dapDataModelSubordinateKeys.stream()
                    .filter(d -> d.getFieldIds().contains(fieldId))
                    .map(DapDataModelSubordinateKey::getFieldIds)
                    .collect(Collectors.joining(","));
            if(StringUtils.isNotBlank(collect)){
                return fieldId;
            }
        }
        return null;
    }*/

    /**
     * 判断新增索引是否重复
     * @param list
     * @return
     */
    @Override
    public List<String> isRepeat(List<DapDataModelSubordinateKey> list) {

        // 检查索引名是否重复
        List<String> keys = list.stream().map(DapDataModelSubordinateKey::getKeyName).collect(Collectors.toList());
        // 不区分大小写
        List<String> collect = keys.stream().map(f -> f.toLowerCase()).collect(Collectors.toList());
        return CheckUtils.getDuplicateElements(collect);
    }

    /**
     * 导入excel索引
     * @param fields
     * @param keys
     */
    @Override
    public void importExcelKeys(List<DapDataModelTableField> fields, List<DapDataModelSubordinateKey> keys) {

        // 获得到字段的集合
        for (DapDataModelSubordinateKey key: keys) {
            // 获得索引字段
            List<String> strings = Arrays.asList(key.getFieldIds().split(","));
            // 匹配索引字段，获得字段id
            List<String> collect = fields.stream().filter(f -> strings.contains(f.getFieldName()))
                    .map(DapDataModelTableField::getId).collect(Collectors.toList());
            // 加入索引字段的id长度与索引字段的长度相等
            if(collect.size()==strings.size()){
                key.setFieldIds(StringUtils.join(collect,","));
                key.setModelTableId(fields.get(0).getModelTableId());
                key.setDataModelId(fields.get(0).getDataModelId());
            }else {
                throw new DapException("索引中的字段列表和无法匹配字段，请检查数据的正确性！");
            }
        }
        // 插入操作
        this.saveBatch(keys);
    }

    /**
     * 删除备份索引
     * @param modelId
     */
    @Override
    public void deleteKey(String modelId) {

        dapDataModelSubordinateKeyMapper.deleteKey(modelId);

    }

    /**
     * 新增索引
     * @param keys
     * @return
     */
    @Override
    public ResultBean<Boolean> insertKey(List<DapDataModelSubordinateKey> keys, DatabaseType databaseType) {

        // 获得当前索引的id
        List<String> ids = keys.stream().filter(k -> StringUtils.isNotBlank(k.getId()))
                .map(DapDataModelSubordinateKey::getId).collect(Collectors.toList());
        // 查询数据库中的信息
        if(!ids.isEmpty()){
            List<DapDataModelSubordinateKey> keyList = dapDataModelSubordinateKeyMapper.selectBatchIds(ids);
            boolean flag = keyList.stream().noneMatch(k -> k.getBmStatus() == BmStatus.DELETE);
            // 检查是否有删除的数据
            if(!flag){
                return ResultBean.error("索引列表存在已删除的数据，请刷新页面");
            }
        }
        // 检查新增的数据是否和数据库重复
        List<String> keyNames = keys.stream().filter(f -> StringUtils.isBlank(f.getId()))
                .map(DapDataModelSubordinateKey::getKeyName).collect(Collectors.toList());
        List<DapDataModelSubordinateKey> sameKeys = Lists.newArrayList();
        // 查询库中是否有相同的数据
        if(!keyNames.isEmpty()){
            if(databaseType.equals(DatabaseType.MYSQL)){
                sameKeys = dapDataModelSubordinateKeyMapper.selectList(new LambdaQueryWrapper<DapDataModelSubordinateKey>()
                        .eq(DapDataModelSubordinateKey::getBmStatus, BmStatus.ON.getCode())
                        .eq(DapDataModelSubordinateKey::getModelTableId, keys.get(0).getModelTableId())
                        .in(DapDataModelSubordinateKey::getKeyName, keyNames));
            }else {
                sameKeys = isRepeatInSystem(keys.get(0).getDataModelId(), keyNames);
            }
            if(!sameKeys.isEmpty()){
                return ResultBean.error("数据库存在重复索引名");
            }
        }

        List<String> idKeyNames = keys.stream().filter(f -> StringUtils.isNotBlank(f.getId()))
                .map(DapDataModelSubordinateKey::getKeyName).collect(Collectors.toList());
        // 编辑的情况
        if(databaseType.equals(DatabaseType.PGSQL) && !idKeyNames.isEmpty()){
            // 新增的索引
            List<String> newIds = keys.stream().filter(f -> StringUtils.isNotBlank(f.getId()))
                    .map(DapDataModelSubordinateKey::getId).collect(Collectors.toList());
            List<DapDataModelSubordinateKey> idKeys = isRepeatInSystem(keys.get(0).getDataModelId(), idKeyNames);
            // 库里的索引
            List<String> oldIds = idKeys.stream().filter(f -> StringUtils.isNotBlank(f.getId()))
                    .map(DapDataModelSubordinateKey::getId).collect(Collectors.toList());
            // 索引名重复的id
            List<String> collect = oldIds.stream().filter(n -> !newIds.contains(n)).collect(Collectors.toList());
            String names = idKeys.stream().filter(i -> collect.contains(i.getId()))
                    .map(DapDataModelSubordinateKey::getKeyName).collect(Collectors.joining(","));
            if(StringUtils.isNotBlank(names)){
                return ResultBean.error("pg数据库存在重复索引名:" + names);
            }
        }
        List<DapDataModelSubordinateKey> collect = keys.stream().peek(k -> k.setUpdateTime(null)).collect(Collectors.toList());
        return ResultBean.ok(this.saveOrUpdateBatch(collect));
    }

    /**
     * 新增pg索引是否在系统中重复
     * @param modelId
     * @return
     */
    @Override
    public List<DapDataModelSubordinateKey> isRepeatInSystem(String modelId, List<String> keyNames) {
        // 查询当前系统下的模型列表
        DapDataModel dapDataModel = dapDataModelService.getBaseMapper().selectById(modelId);
        // 查询该系统下的模型
        List<DapDataModel> dapDataModels = dapDataModelService.getModelListById(dapDataModel.getSystemId());
        List<String> collect = dapDataModels.stream().map(DapDataModel::getId).collect(Collectors.toList());
        // pgsql 要求模型内索引唯一
        List<DapDataModelSubordinateKey> sameKeys = dapDataModelSubordinateKeyMapper.selectList(new LambdaQueryWrapper<DapDataModelSubordinateKey>()
                .eq(DapDataModelSubordinateKey::getBmStatus, BmStatus.ON.getCode())
                .in(DapDataModelSubordinateKey::getDataModelId, collect)
                .eq(DapDataModelSubordinateKey::getPId, "0")
                .in(DapDataModelSubordinateKey::getKeyName, keyNames));
        return sameKeys;
    }
}
